﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Matter     //对应了 场景中被实例化出来的一个物质  首先会有 MatterType  定义了这是个什么东西
{


    static Stack<Matter> caches = new Stack<Matter>();
    static public Matter Creat()
    {
        if(caches.Count == 0)
        {
            return new Matter();
        }
        return caches.Pop();
    }

    public static void Delete(Matter m)
    {
        caches.Push(m);
    }


    public enum MatterState
    {
        Solid,              //固体
        SolidAndLiquid,     //固液混合状态  一般来说计算过程中使用 计算结束后 会拆成2个物体
        Liquid,             //液体
        LiquidAndGas,       //气体和液体    一般来说计算过程中使用 计算结束后 会拆成2个物体
        Gas,                //气体
    }

    public static string ConvertStateToString(MatterState ms)
    {
        switch(ms)
        {
            case MatterState.Gas:
                return "气体";
            case MatterState.LiquidAndGas:
                return "气液混合";
            case MatterState.Liquid:
                return "液体";
            case MatterState.SolidAndLiquid:
                return "固液混合";
            case MatterState.Solid:
                return "固体";
        }
        return "Wrong";
    }

    public static MatterState ConvertStateFromString(string str)
    {

        switch (str)
        {
            case "气体":
            case "gas":
                return MatterState.Gas;
            case "气液混合":
            case "LiquidAndGas":
                return MatterState.LiquidAndGas;
            case "液体":
            case "Liquid":
                return MatterState.Liquid;
            case "固液混合":
            case "SolidAndLiquid":
                return MatterState.SolidAndLiquid;
            case "固体":
            case "Solid":
                return MatterState.Solid;
        }
        return MatterState.Solid;
    }



    public float Temperature;   //温度        单位 摄氏度
    public float Mass;          //质量        单位 KG
    public MatterState currentMatterState;
    public MatterType matterType;

    public Matter Clone()
    {
        Matter m = this.MemberwiseClone() as Matter;
        return m;
    }

    public Matter Clone(float temp)
    {
        Matter m = this.MemberwiseClone() as Matter;
        m.Temperature = temp;
        return m;
    }



    public void CheckMatterState()
    {
        if (Temperature < matterType.MeltingPoint)
        {
            currentMatterState = MatterState.Solid;
        }
        else if (Temperature == matterType.MeltingPoint)
        {
            currentMatterState = MatterState.SolidAndLiquid;
        }
        else if (Temperature > matterType.MeltingPoint && Temperature < matterType.BoilingPoint)
        {
            currentMatterState = MatterState.Liquid;
        }
        else if (Temperature == matterType.BoilingPoint)
        {
            currentMatterState = MatterState.LiquidAndGas;
        }
        else
        {
            currentMatterState = MatterState.Gas;
        }
    } 


    /// <summary>
    /// 调用者 保证 startT  和 endt 不跨状态
    /// </summary>
    /// <param name="startT"></param>
    /// <param name="endT"></param>
    public void CheckMatterState(float startT,float endT)
    {
        if (startT <= matterType.MeltingPoint && endT <= matterType.MeltingPoint)
        {
            currentMatterState = MatterState.Solid;
        }
        else if(startT <= matterType.BoilingPoint && endT<= matterType.BoilingPoint)
        {
            currentMatterState =  MatterState.Liquid;
        }
        else if(startT >=matterType.BoilingPoint && endT >= matterType.BoilingPoint )
        {
            currentMatterState = MatterState.Gas;
        }
    }



    public Matter EnergyChange(float dEnergy, List<MyMathHelp.MultiSegmentFunction.Segment> segments)     //发生能量变化 如果停下的能量正好是处于 转换的过程中 则有可能产生2个物体
    {
        if(dEnergy > 0)
        {
            #region 温度上升
            for(int i = 0;i < segments.Count;i++)
            {
                if(dEnergy > segments[i].StartPoint.x && dEnergy < segments[i].EndPoint.x)
                {
                    if(segments[i].StartPoint.y != segments[i].EndPoint.y)
                    {
                        Temperature = segments[i].StartPoint.y + (segments[i].EndPoint.y - segments[i].StartPoint.y) * (dEnergy - segments[i].StartPoint.x) / (segments[i].EndPoint.x - segments[i].StartPoint.x);
                        CheckMatterState(segments[i].StartPoint.y, segments[i].EndPoint.y);
                        return null;
                    }
                    else
                    {
                        Temperature = segments[i].StartPoint.y;
                        float percent = (dEnergy - segments[i].StartPoint.x) / (segments[i].EndPoint.x - segments[i].StartPoint.x);
                        //如果正好在状态转换过程中
                        CheckMatterState();
                        if(currentMatterState == MatterState.SolidAndLiquid)
                        {
                            currentMatterState = MatterState.Solid;
                            float liquidm = Mass * percent;
                            Mass = Mass * (1 - percent);
                            Matter other = this.Clone();
                            other.currentMatterState = MatterState.Liquid;
                            other.Mass = liquidm;
                            return other;
                        }
                        else if(currentMatterState == MatterState.LiquidAndGas)
                        {
                            currentMatterState = MatterState.Liquid;
                            float gasm = Mass * percent;
                            Mass = Mass * (1 - percent);
                            Matter other = this.Clone();
                            other.currentMatterState = MatterState.Gas;
                            other.Mass = gasm;
                            return other;
                        }
                        else
                        {
                            Debug.LogError("状态错误 , 现在应该处于混合物 恒温状态");
                        }
                    }
                }
            }
            #endregion
        }
        else
        {
            #region 温度下降
            float tempdEnergy = -dEnergy;
            for (int i = 0; i < segments.Count; i++)
            {
                if (tempdEnergy > segments[i].StartPoint.x && tempdEnergy <= segments[i].EndPoint.x)
                {
                    if (segments[i].StartPoint.y != segments[i].EndPoint.y)
                    {
                        Temperature = segments[i].StartPoint.y + (segments[i].EndPoint.y - segments[i].StartPoint.y) * (tempdEnergy - segments[i].StartPoint.x) / (segments[i].EndPoint.x - segments[i].StartPoint.x);
                        CheckMatterState(segments[i].StartPoint.y,segments[i].EndPoint.y);
                        //如果 在边界线上的话 可能会出现 == 熔点或者沸点的情况 造成误判

                        if(currentMatterState == MatterState.LiquidAndGas)
                        {
                            Debug.LogError("错误 ");
                        }
                        return null;
                    }
                    else
                    {
                        Temperature = segments[i].StartPoint.y;
                        float percent = (tempdEnergy - segments[i].StartPoint.x) /(segments[i].EndPoint.x - segments[i].StartPoint.x);
                        //如果正好在状态转换过程中
                        CheckMatterState();
                        if (currentMatterState == MatterState.SolidAndLiquid)
                        {
                            currentMatterState = MatterState.Liquid;
                            float liquidm = Mass * percent;
                            Mass = Mass * (1 - percent);
                            Matter other = this.Clone();
                            other.currentMatterState = MatterState.Gas;
                            other.Mass = liquidm;
                            return other;
                        }
                        else if (currentMatterState == MatterState.LiquidAndGas)
                        {
                            currentMatterState = MatterState.Gas;
                            float gasm = Mass * percent;
                            Mass = Mass * (1 - percent);
                            Matter other = this.Clone();
                            other.currentMatterState = MatterState.Liquid;
                            other.Mass = gasm;
                            return other;
                        }
                        else
                        {
                            Debug.LogError("状态错误 , 现在应该处于混合物 恒温状态");
                        }
                    }
                }
            }
            #endregion

        }
        return null;
    }
    public float GetMaxTempStateChange()
    {
        if(currentMatterState == MatterState.Gas)
        {
            return matterType.BoilingPoint;
        }
        if(currentMatterState == MatterState.Liquid)
        {
            return matterType.MeltingPoint;
        }
        return float.MinValue;
    }

    public float GetMinTempStateChange()
    {
        if(currentMatterState == MatterState.Solid)
        {
            return matterType.MeltingPoint;
        }
        if(currentMatterState == MatterState.Liquid)
        {
            return matterType.BoilingPoint;
        }
        return float.MaxValue;
    }

    /// <summary>
    /// 得到 从绝对零度开始计算的 所有能量 包括把可能的溶解热和气化热都计算进去
    /// </summary>
    /// <returns>能量</returns>
    public float GetTotalEnergy()
    {
        switch(currentMatterState )
        {
            case MatterState.Solid:
                return Mass * (Temperature  - GlobalConst.AbsoluteZero) * matterType.SpecificHeat;
            case MatterState.Liquid:
                return Mass * (Temperature - GlobalConst.AbsoluteZero) * matterType.SpecificHeat + Mass * matterType.HeatOfFusion;
            case MatterState.Gas:
                return Mass * (Temperature - GlobalConst.AbsoluteZero) * matterType.SpecificHeat + Mass * matterType.HeatOfFusion + Mass * matterType.HeatOfGasification;
        } 
        return 0.0f;
    }


    /// <summary>
    /// 只有 固体 和液体 才能获得体积  气体是有多大就多大 无法得到体积
    /// </summary>
    /// <returns></returns>
    public float GetVolume()
    {
        if(currentMatterState == MatterState.Liquid)
        {
            return Mass / matterType.DensityWhenLiquid;
        }
        if(currentMatterState == MatterState.Solid)
        {
            return Mass / matterType.DensityWhenSolid;
        }
        return 0.0f;
    }

    /// <summary>
    /// 计算气体物质在 特定的体积 及 温度下的压强
    /// </summary>
    /// <param name="volume"> 体积 单位 立方米</param>
    /// <param name="temperature">温度  单位 摄氏度</param>
    /// <returns></returns>
    public float GetGasPressure(float volume,float temperature)
    {
        if(currentMatterState != MatterState.Gas)
        {
            return 0.0f;
        }
        return GlobalConst.GetPressure(Mass, matterType.AtomicWeight, temperature, volume);
    }

    //返回自己的热力学折线方程
    public List<MyMathHelp.MultiSegmentFunction.Segment> BuildSegment( bool add)
    {
        if (add)    //如果是往上走
        {
            #region  温度升高
            switch(currentMatterState)
            {
                case MatterState.Gas:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 f = new Vector2(a.x + matterType.SpecificHeat * Mass * (GlobalConst.MaxTemperature - Temperature ), GlobalConst.MaxTemperature);
                        return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a, f });
                    }
                case MatterState.Liquid:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 d = new Vector2(a.x + matterType.SpecificHeat * Mass * (Temperature - matterType.BoilingPoint), matterType.BoilingPoint);
                        Vector2 e = new Vector2(d.x + matterType.HeatOfGasification * Mass, matterType.BoilingPoint);
                        Vector2 f = new Vector2(e.x + matterType.SpecificHeat * Mass * (GlobalConst.MaxTemperature - d.y), GlobalConst.MaxTemperature);
                        return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a, d, e, f });

                    }
                case MatterState.Solid:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 b = new Vector2(matterType.SpecificHeat * Mass * (matterType.MeltingPoint - Temperature), matterType.MeltingPoint);
                        Vector2 c = new Vector2(b.x + matterType.HeatOfFusion * Mass, matterType.MeltingPoint);
                        Vector2 d = new Vector2(c.x + matterType.SpecificHeat * Mass * (matterType.BoilingPoint - matterType.MeltingPoint), matterType.BoilingPoint);
                        Vector2 e = new Vector2(d.x + matterType.HeatOfGasification * Mass, matterType.BoilingPoint);
                        Vector2 f = new Vector2(e.x + matterType.SpecificHeat * Mass * (GlobalConst.MaxTemperature - d.y), GlobalConst.MaxTemperature);
                        return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a, b, c, d, e, f });
                    }
            }
            #endregion
        }
        else
        {
            #region 温度降低
            switch(currentMatterState)
            {
                case MatterState.Gas:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 b = new Vector2(matterType.SpecificHeat * Mass * (Temperature - matterType.BoilingPoint), matterType.BoilingPoint);
                        Vector2 c = new Vector2(b.x + matterType.HeatOfGasification * Mass, matterType.BoilingPoint);
                        Vector2 d = new Vector2(c.x + matterType.SpecificHeat * Mass*(matterType.BoilingPoint - matterType.MeltingPoint), matterType.MeltingPoint);
                        Vector2 e = new Vector2(d.x + matterType.HeatOfFusion * Mass, matterType.MeltingPoint);
                        Vector2 f = new Vector2(e.x + matterType.SpecificHeat * Mass * (d.y - (-300.0f)), -300.0f);
                        if (Temperature == matterType.BoilingPoint)
                        {
                            return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { b, c, d, e, f });
                        }
                        else
                        {
                            return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a, b, c, d, e, f });
                        }
                    }
                case MatterState.Liquid:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 d = new Vector2(a.x + matterType.SpecificHeat * Mass * (Temperature - matterType.MeltingPoint), matterType.MeltingPoint);
                        Vector2 e = new Vector2(d.x + matterType.HeatOfFusion * Mass, matterType.MeltingPoint);
                        Vector2 f = new Vector2(e.x + matterType.SpecificHeat * Mass * (d.y - (-300.0f)), -300.0f);
                        return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a, d, e, f });
                    }
                case MatterState.Solid:
                    {
                        Vector2 a = new Vector2(0.0f, Temperature);
                        Vector2 f = new Vector2(a.x + matterType.SpecificHeat * Mass * (Temperature - (-300.0f)), -300.0f);
                        return MyMathHelp.MultiSegmentFunction.Build(new List<Vector2>() { a,f });
                    }
            }
            #endregion
        }
        return null;
    }

}

public class MatterType         //定义了物质的各种属性   比如 二氧化碳 对应的 一个MatterType
{
    /// <summary>
    /// 比热        单位 KJ/(度*千克)
    /// </summary>
    public float SpecificHeat;

    ///<summary>
    /// 熔点       单位 摄氏度
    ///</summary>              
    public float MeltingPoint;              

    public float BoilingPoint;              //沸点       单位 摄氏度  一个标准大气压下的沸点
    public float DensityWhenSolid;          //固定时密度
    public float DensityWhenLiquid;         //液体时密度  气体时的密度 通过原子量 温度 和 气压计算得出   kg/m^3
    public float HeatTransferCoefficient;   //传热系数    单位 W/(m·K)
    public float AtomicWeight;              //原子量       用来计算被气化后 的 密度 压强等 
    public float HeatOfGasification;        //汽化热       KJ/KG

    public float HeatOfFusion;              //熔化热       KJ/KG   
    public float SurfaceTensionOfLiquid;     //液体表面张力    N/M
    public string Name;                     //物质的名字  比如二氧化碳

    public string SolidSpriter;             //固体的时候使用图片
    public string LiquidSpriter;            //液体的时候使用的图片
    public float ShowPriority = 1.0f;              //显示的优先级  有些物体 质量不高 但希望已非常高的优先级进行显示 范围0.01 到1000000;   
}

